package org.tema.web;

import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.TimeZone;

import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.faces.component.html.HtmlDataTable;
import javax.faces.component.html.HtmlInputHidden;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.persistence.NoResultException;

import org.tema.Priority;
import org.tema.Status;
import org.tema.Type;
import org.tema.ejb.ProductBeanLocal;
import org.tema.ejb.TestCaseBeanLocal;
import org.tema.ejb.TestPlanBeanLocal;
import org.tema.ejb.TestSpecBeanLocal;
import org.tema.entities.Product;
import org.tema.entities.TestCase;
import org.tema.entities.TestPlan;
import org.tema.entities.TestSpecification;
import org.tema.entities.User;

public class ManageTestCasesBean {

	// navigation constants
	private static final String CASES_LIST = "casesList";
	private static final String EDIT_CASE= "editCase";
	
	@EJB private TestSpecBeanLocal testSpecBean;
	@EJB private ProductBeanLocal productBean;
	@EJB private TestCaseBeanLocal testCaseBean;
	@EJB private TestPlanBeanLocal testPlanBean;
	private  TestCaseSearchTypes searchDropDown;
	
	private Collection <TestCase> testCaseList = null;
	private int testCaseId;
	private TestCase singleTestCase;
	private User user;
	private HtmlDataTable dataTable;
	
	//UI Search word for the drop down menus
	private Type searchWordType;
	private String searchWordSpec;
	private Status searchWordStatus;
	private Priority searchWordPriority;
	private String searchWord;
	private String searchWordBugID;
	//individual variables for a Test Case Bean Management
	private String summary;
	private String environment;
	private String preSteps;
	private String description;
	private String expectedResult;
	private int[] bugId;
	private Date  cDate;
	private Date  mDate;
	private byte[] attachment;
	private Priority priority;
	private Type type;
	private Status status;
	private double executionTime;
	private HtmlInputHidden dataItemId = new HtmlInputHidden();
	
	public  ManageTestCasesBean() {
		// constructor
	}

	public HtmlDataTable getDataTable() {
		return dataTable;
	}

	public void setDataTable(HtmlDataTable dataTable) {
		this.dataTable = dataTable;
	}

	public HtmlInputHidden getDataItemId() {
		return dataItemId;
	}

	public void setDataItemId(HtmlInputHidden dataItemId) {
		this.dataItemId = dataItemId;
	}


	public String getDescription() {
		return description;
	}


	public void setDescription(String description) {
		this.description = description;
	}
	
	///real methods besides accessors
	
	
	public TestCaseSearchTypes getSearchDropDown() {
		return searchDropDown;
	}


	public void setSearchDropDown(TestCaseSearchTypes searchDropDown) {
		this.searchDropDown = searchDropDown;
	}


	public String getSearchWord() {
		return searchWord;
	}


	public String getSummary() {
		return summary;
	}

	public void setSummary(String summary) {
		this.summary = summary;
	}

	public Date getCDate() {
		return cDate;
	}

	public void setCDate(Date date) {
		date = new java.sql.Date(System.currentTimeMillis());
		cDate = date;
	}

	public Date getMDate() {
		return mDate;
	}

	public void setMDate(Date date) {
		//date = new java.sql.Date(System.currentTimeMillis());
		mDate = date;
	}

	public Collection<TestCase> getTestCaseList() {
		if( testCaseList == null ){
			findAll();
		}
		return testCaseList;
	}

	public void setTestCaseList(Collection<TestCase> testCaseList) {
		this.testCaseList = testCaseList;
	}

	public TestCase getSingleTestCase() {
		return singleTestCase;
	}

	public void setSingleTestCase(TestCase singleTestCase) {
		this.singleTestCase = singleTestCase;
	}

	public void setSearchWord(String searchWord) {
		this.searchWord = searchWord;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public int getTestCaseId() {
		return testCaseId;
	}

	public void setTestCaseId(int testCaseId) {
		this.testCaseId = testCaseId;
	}

	public String getEnvironment() {
		return environment;
	}

	public void setEnvironment(String environment) {
		this.environment = environment;
	}

	public String getPreSteps() {
		return preSteps;
	}

	public void setPreSteps(String preSteps) {
		this.preSteps = preSteps;
	}

	public String getExpectedResult() {
		return expectedResult;
	}

	public void setExpectedResult(String expectedResult) {
		this.expectedResult = expectedResult;
	}

	public int[] getBugId() {
		return bugId;
	}

	public void setBugId(int[] bugId) {
		this.bugId = bugId;
	}

	public byte[] getAttachment() {
		return attachment;
	}

	public void setAttachment(byte[] attachment) {
		this.attachment = attachment;
	}

	public Priority getPriority() {
		return priority;
	}

	public void setPriority(Priority priority) {
		this.priority = priority;
	}

	public Type getType() {
		return type;
	}

	public void setType(Type type) {
		this.type = type;
	}

	public Status getStatus() {
		return status;
	}

	public void setStatus(Status status) {
		this.status = status;
	}

	public double getExecutionTime() {
		return executionTime;
	}

	public void setExecutionTime(double executionTime) {
		this.executionTime = executionTime;
	}

	
	public Type getSearchWordType() {
		return searchWordType;
	}

	public void setSearchWordType(Type searchWordType) {
		this.searchWordType = searchWordType;
	}

	public String getSearchWordSpec() {
		return searchWordSpec;
	}

	public void setSearchWordSpec(String searchWordSpec) {
		this.searchWordSpec = searchWordSpec;
	}

	public Status getSearchWordStatus() {
		return searchWordStatus;
	}

	public void setSearchWordStatus(Status searchWordStatus) {
		this.searchWordStatus = searchWordStatus;
	}

	public Priority getSearchWordPriority() {
		return searchWordPriority;
	}

	public void setSearchWordPriority(Priority searchWordPriority) {
		this.searchWordPriority = searchWordPriority;
	}


	public String getSearchWordBugID() {
		return searchWordBugID;
	}

	public void setSearchWordBugID(String searchWordBugID) {
		this.searchWordBugID = searchWordBugID;
	}

	public TimeZone getTimeZone() {
		return TimeZone.getDefault();
	}

	/////start of methods that are not accessors//////////////////////
	public String createTestCase() {
		Date creationD  = new java.sql.Date(System.currentTimeMillis());
		Date modificationD  = new java.sql.Date(System.currentTimeMillis());
		//status test type and priority should be converted from the search word
		//TestSpecification ts = testSpecBean.findTestSpecBySummary(searchWordSpec);
		//(Type testType, Status testStatus, Priority testPriority, String summary, String environment, String preSteps, String description, String expectedResult, Date creationD, Date modificationD,float executionTime);
		int bugID;
		if ( this.getSearchWordBugID() != null && !( this.getSearchWordBugID().equals("") ) && !( this.getSearchWordBugID().equals(" ") )  ){
			bugID = Integer.parseInt( this.getSearchWordBugID() );
		}
		else {
			bugID=0;
		}
    	FacesContext facesContext = FacesContext.getCurrentInstance(); 
    	String creatorName = facesContext.getExternalContext().getRemoteUser();
		testCaseBean.addTestCase( bugID , this.getSearchWordSpec() , this.getSearchWordType(), this.getSearchWordStatus(), this.getSearchWordPriority(), this.getSummary(), this.getEnvironment(), this.getPreSteps(), this.getDescription(), this.getExpectedResult(), creationD, modificationD, this.getExecutionTime(), creatorName);
		// update test cases list
		findAll();
		// add status message
		org.tema.web.Status.addInfo("Test case " + this.summary + " created. ");
		return CASES_LIST; 
	}
	
	public String deleteTestCase() {
		singleTestCase = (TestCase) dataTable.getRowData();
		testCaseBean.deleteTestCase(singleTestCase);
		// update test cases list
		findAll();
		// add status message
		org.tema.web.Status.addInfo("Test case " + this.summary + " deleted. ");
		return CASES_LIST;
	}
	
	
	public String displayCase() {
		TestCase case1 = (TestCase) dataTable.getRowData();
		this.setSingleTestCase ( testCaseBean.findTestCaseById(case1.getId()) );
		return EDIT_CASE;
	}
	
	public String editTestCase() {
    	FacesContext facesContext = FacesContext.getCurrentInstance(); 
    	String creatorName = facesContext.getExternalContext().getRemoteUser();
		Date date = new Date (System.currentTimeMillis());
		singleTestCase.setModificationDate(date);
		int bug=0;
		if (searchWordBugID.equals("")) {
			testCaseBean.updateTestCase( getSingleTestCase(), bug, creatorName );
		} else {
			bug = Integer.parseInt(searchWordBugID);
			testCaseBean.updateTestCase( getSingleTestCase(), bug, creatorName );
		}
		// update test cases list
		findAll();
		// add status message
		org.tema.web.Status.addInfo("Test case " + this.summary + " modified. ");
		return CASES_LIST;
	}
	
	
	public String  selectSearch(){
		String result;
		switch (this.getSearchDropDown()) {
        case ID:  result = findById( this.getSearchWord()); break;
        case SUMMARY:  result = findBySummary(this.getSearchWord()); break;
        case PRODUCTID:  result = findByProductId(this.getSearchWord()); break;
        case PRODUCTSUMMARY:  result = findByProductName(this.getSearchWord()); break;
        case SPECID:  result = findBySpecId(this.getSearchWord()); break;
        case MDATE:  result = findByModificationD(this.getSearchWord()); break;
        case CDATE:  result = findByCreationD(this.getSearchWord()); break;
        case SPECSUMMARY:  result = findBySpecSummary(this.getSearchWord()); break;
        case TYPE:  result = findByType(this.getSearchWord()); break;
        case STATUS:  result = findByStatus(this.getSearchWord()); break;
        case PRIORITY:  result = findByPriority(this.getSearchWord()); break;
        case PLANID:  result = findByPlanId(this.getSearchWord()); break;
        case PLANSUMMARY:  result = findByPlanSummary(this.getSearchWord()); break;
        case CREATOR:  result = findByCreatorName(this.getSearchWord()); break;
        case MODIFIER:  result = findByModifierName(this.getSearchWord()); break;
        case ALLTESTCASES: result = findAll();
        default: result = findAll();
		}
		return result;
	}
	
	////
	public String  findAll(){
		//String result;
		setTestCaseList( ( Collection <TestCase> ) testCaseBean.findAllTestCases());
		if ( ! getTestCaseList().isEmpty() ){
			return CASES_LIST;
		}
		else {
			return CASES_LIST;
		}
	}
	
	public String findByStatus( String s ){
		for(Status tt : Status.values()) {
			if( s.equals(tt.toString())) {
				setTestCaseList( testCaseBean.findTestCaseByStatus( tt) );
				if(  this.getTestCaseList().isEmpty() ){
					org.tema.web.Status.addInfo("No test cases available with status: " + s );
					return CASES_LIST;
				}
				break;
			}
		}
		return CASES_LIST;
	}
	
	public String findByPriority( String s ){
		for(Priority tt : Priority.values()) {
			if( s.equals(tt.toString())) {
				setTestCaseList( testCaseBean.findTestCaseByPriority( Priority.valueOf(s)) );
				if(  this.getTestCaseList().isEmpty() ){
					org.tema.web.Status.addInfo("No test cases available with priority: " + s );
					return CASES_LIST;
				}
				break;
			}
		}
		return CASES_LIST;
	}
	
	public String findByType( String s ){
		for(Type tt : Type.values()) {
			if( s.equals(tt.toString())) {
				setTestCaseList( testCaseBean.findTestCaseByType( tt) );
				if(  this.getTestCaseList().isEmpty() ){
					org.tema.web.Status.addInfo("No test cases available with type: " + s );
					return CASES_LIST;
				}
				break;
			}
		}
		return CASES_LIST;
	}
	
	public String  findById(String searchWord){
		setTestCaseId( Integer.parseInt(searchWord));
		try {
			setSingleTestCase( testCaseBean.findTestCaseById(getTestCaseId()));
			this.setTestCaseList(Arrays.asList(singleTestCase));
			return CASES_LIST;
		} catch (NoResultException e) {
			return CASES_LIST;
		}
		catch(IllegalArgumentException il){
			return CASES_LIST;
		}
		catch(EJBException e){
			org.tema.web.Status.addError(e.getCause().getMessage());
			return CASES_LIST;
		}
	}
	
	
	
	@SuppressWarnings("unchecked")
	public String findBySummary( String searchWord){
			try {
				setTestCaseList( ( Collection <TestCase> ) testCaseBean.findTestCasesBySummary(searchWord));
				if (  getTestCaseList().isEmpty() ){
					//status message
					org.tema.web.Status.addInfo("No test cases available with summary: " + searchWord );
					return CASES_LIST;
				}
				else {
					return CASES_LIST;
				}
			}
			catch(IllegalArgumentException il){
				return CASES_LIST;
			}
			catch(EJBException e){
				org.tema.web.Status.addError(e.getCause().getMessage());
				return CASES_LIST;
			}
	}


	@SuppressWarnings("unchecked")
	public String findByProductId(String searchWord ){
		int id =  Integer.parseInt(searchWord);
		Product p = this.productBean.findProductById(id);
		try{
			this.setTestCaseList( (Collection <TestCase>) p.getTestCaseSet() );
			if (  getTestCaseList().isEmpty() ){
				//status message
				org.tema.web.Status.addInfo("No test cases available with product id: " + id );
				return CASES_LIST;
			}
			else {
				return CASES_LIST;
			}
		}
		catch(IllegalArgumentException il){
			return CASES_LIST;
		}
		catch(EJBException e){
			org.tema.web.Status.addError(e.getCause().getMessage());
			return CASES_LIST;
		}
	}
	
	
	@SuppressWarnings("unchecked")
	public String findByProductName(String SearchWord ){
		try{
			this.setTestCaseList( (Collection <TestCase>) productBean.findProductByName(searchWord).getTestCaseSet() );
			if (  getTestCaseList().isEmpty() ){
				//status message
				org.tema.web.Status.addInfo("No test cases available with product name: " + searchWord );
				return CASES_LIST;
			}
			else {
				return CASES_LIST;
			}
		}
		catch(IllegalArgumentException il){
				return CASES_LIST;
		}
		catch(EJBException e){
			org.tema.web.Status.addError(e.getCause().getMessage());
			return CASES_LIST;
		}
	}
	
	//convert string to date for the creation and modification dates
	public Date convertString (String strDate){
		Date date = null;
		try{
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd");
			date = new Date( sdf.parse(strDate).getTime() );
		}catch(ParseException pe){
			pe.getMessage();
			pe.printStackTrace();
		}
		return date;
	}
	
	
	public String findByCreationD(String cDate){
		try{
			this.setTestCaseList( (Collection <TestCase>) testCaseBean.findTestCaseByCDate( convertString(cDate) )  );
			if (  getTestCaseList().isEmpty() ){
				//status message
				org.tema.web.Status.addInfo("No test cases available with creation date: " + cDate );
			}
		}
		catch(EJBException e){
				org.tema.web.Status.addError(e.getCause().getMessage());
		}
		return CASES_LIST;
	}
	
	public String findByModificationD(String cDate){
		try{
			this.setTestCaseList( (Collection <TestCase>) testCaseBean.findTestCaseByMDate( convertString(cDate) )   );
			if (  getTestCaseList().isEmpty() ){
				//status message
				org.tema.web.Status.addInfo("No test cases available with modification date: " + cDate );
			}
		}
		catch(EJBException e){
				org.tema.web.Status.addError(e.getCause().getMessage());	
		}
		return CASES_LIST;
	}
	
	public String findByCreatorName(String cName){
		try {
			this.setTestCaseList( (Collection <TestCase>) testCaseBean.findTestCaseByCreatorName(cName)  );
			if (  getTestCaseList().isEmpty() ){
				//status message
				org.tema.web.Status.addInfo("No test cases available with creator: " + cName );
			}
			return CASES_LIST;
		}
		catch(IllegalArgumentException il){
			return CASES_LIST;
		}
		catch(EJBException e){
			org.tema.web.Status.addError(e.getCause().getMessage());
			return CASES_LIST;
		}
	
	}
	
	public String findByModifierName(String mName){
		try{
			this.setTestCaseList( (Collection <TestCase>) testCaseBean.findTestCaseByModifierName(mName));
			if (  getTestCaseList().isEmpty() ){
				//status message
				org.tema.web.Status.addInfo("No test cases available with modifier: " + mName );
			}
			return CASES_LIST;
		}
		catch(IllegalArgumentException il){
			return CASES_LIST;
		}
		catch(EJBException e){
			org.tema.web.Status.addError(e.getCause().getMessage());
			return CASES_LIST;
		}
	}
	
	@SuppressWarnings("unchecked")
	public String findBySpecId(String searchWord){
		int id = Integer.parseInt(searchWord);
		TestSpecification ts = testSpecBean.findTestSpecById(id);
		try{
			this.setTestCaseList( (Collection <TestCase>) ts.getTestCaseSet() );
			if ( getTestCaseList().isEmpty() ){
				if (  getTestCaseList().isEmpty() ){
					//status message
					org.tema.web.Status.addInfo("No test cases available with specification id: " + id );
				}
				return CASES_LIST;
			}
			else {
				return CASES_LIST;
			}
		}
		catch(IllegalArgumentException il){
			return CASES_LIST;
		}
		catch(EJBException e){
			org.tema.web.Status.addError(e.getCause().getMessage());
			return CASES_LIST;
		}
		
	}
	
	@SuppressWarnings("unchecked")
	public String findBySpecSummary(String searchWord){
		try{
			this.setTestCaseList( (Collection <TestCase>) testSpecBean.findTestSpecBySummary(searchWord).getTestCaseSet() );
			if (  getTestCaseList().isEmpty() ){
				//status message
				org.tema.web.Status.addInfo("No test cases available with specification summary: " + searchWord );
				return CASES_LIST;
			}
			else {
				return CASES_LIST;
			}
		}
		catch(IllegalArgumentException il){
			return CASES_LIST;
		}
		catch(EJBException e){
			org.tema.web.Status.addError(e.getCause().getMessage());
			return CASES_LIST;
		}
	}
	

	
	
	@SuppressWarnings("unchecked")
	public String findByPlanId(String searchWord){
		int id = Integer.parseInt(searchWord);
		TestPlan tp = testPlanBean.findTestPlanById(id);
		try{
			this.setTestCaseList( (Collection <TestCase>) tp.getTestCaseSet() );
			if (  getTestCaseList().isEmpty() ){
				//status message
				org.tema.web.Status.addInfo("No test cases available with plan id : " + id  );
				return CASES_LIST;
			}
			else {
				return CASES_LIST;
			}
		}catch(IllegalArgumentException il){
			return CASES_LIST;
		}
		catch(EJBException e){
			org.tema.web.Status.addError(e.getCause().getMessage());
			return CASES_LIST;
		}
		
	}
	
	@SuppressWarnings("unchecked")
	public String findByPlanSummary(String searchWord){
		try{
			this.setTestCaseList( (Collection <TestCase>) testPlanBean.findTestPlanBySummary(searchWord).getTestCaseSet() );
			if (  getTestCaseList().isEmpty() ){
				//status message
				org.tema.web.Status.addInfo("No test cases available with plan summary: " + searchWord );
				return CASES_LIST;
			}
			else {
				return CASES_LIST;
			}
		}catch(IllegalArgumentException il){
			return CASES_LIST;
		}
		catch(EJBException e){
			org.tema.web.Status.addError(e.getCause().getMessage());
			return CASES_LIST;
		}
	}
	
    public Collection<SelectItem> getItems() {
    	TestCaseSearchTypes[] values = TestCaseSearchTypes.values();
        Collection<SelectItem> list = new ArrayList<SelectItem>(values.length);
        for (TestCaseSearchTypes value : values) {            
        	list.add(new SelectItem(value, value.getLabel()));             
        } 
        return list;
    }
    
    public Collection<SelectItem> getPriorityList(){
    	Priority [] pValues = Priority.values();
    	Collection <SelectItem> priorityList = new ArrayList<SelectItem>( pValues.length);  	
    	for( Priority value : pValues ){
    		priorityList.add( new SelectItem(value));
    	}
    	return priorityList;
    }

    public Collection<SelectItem> getTypeList(){
    	Type [] tValues = Type.values();
    	Collection <SelectItem> typeList = new ArrayList<SelectItem>( tValues.length);  	
    	for( Type value : tValues ){
    		typeList.add( new SelectItem(value));
    	}
    	return typeList;
    }
    
    public Collection<SelectItem> getStatusList(){
    	Status [] sValues = Status.values();
    	Collection <SelectItem> statusList = new ArrayList<SelectItem>( sValues.length);  	
    	for( Status value : sValues ){
    		statusList.add( new SelectItem(value));
    	}
    	return statusList;
    }
    
    public Collection<SelectItem> getSpecList(){
    	Collection <SelectItem> specList = new ArrayList<SelectItem>( testSpecBean.findAllTestSpecs().size() );  	
    	for(TestSpecification spec : testSpecBean.findAllTestSpecs() ){
    		specList.add( new SelectItem(spec.getSummary() ) );
    	}
    	return specList;
    }
   
    
    public Collection<SelectItem> getBugs(){	
    	Collection <SelectItem> bugList = new ArrayList<SelectItem>();
    	Collection<Integer> buggys = this.getSingleTestCase().getBugId();
    		if (buggys != null) {
		    	for(int bug : buggys ){
		    		bugList.add( new SelectItem( Integer.toString(bug) ) );
		    	}
    		}
    	
    	return bugList;
    }
    
}
